package com.pxmeta.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pxmeta.common.constant.Status;
import com.pxmeta.common.core.redis.RedisCache;
import com.pxmeta.common.exception.ServiceException;
import com.pxmeta.party.entity.PartyUser;
import com.pxmeta.user.converter.UserBillConverter;
import com.pxmeta.user.entity.User;
import com.pxmeta.user.entity.UserBill;
import com.pxmeta.user.entity.UserBillCategoryEnum;
import com.pxmeta.user.entity.UserBillTypeEnum;
import com.pxmeta.user.entity.dto.ApplyWithdrawDTO;
import com.pxmeta.user.entity.vo.PartyUserBillVO;
import com.pxmeta.user.entity.vo.UserBillVO;
import com.pxmeta.user.mapper.UserBillMapper;
import com.pxmeta.user.service.IUserBillService;
import com.pxmeta.user.service.IUserService;
import com.pxmeta.user.service.IUserWithdrawService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author wcl
 * @since 2022-07-13
 */
@Service
@RequiredArgsConstructor
public class UserBillServiceImpl extends ServiceImpl<UserBillMapper, UserBill> implements IUserBillService {

    @Autowired
    private  IUserService userService;

    @Autowired
    private IUserWithdrawService userWithdrawService;

    @Autowired
    private RedisCache redisCache;


    @Override
    public List<UserBillVO> getCoinRecords(Long userId, Integer page, Integer size) {

        LambdaQueryWrapper<UserBill> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(UserBill::getUserId, userId)
                .eq(UserBill::getCategory, UserBillCategoryEnum.BALANCE.getCategory())
                .ne(UserBill::getNumber,0)
                .orderByDesc(UserBill::getCreateTime);

        List<UserBill> records = this.page(new Page<>(page, size), wrapper).getRecords();
        return UserBillConverter.toVoList(records);
    }

    @Override
    public List<UserBillVO> getProfitRecords(Long userId, Integer page, Integer size) {

        LambdaQueryWrapper<UserBill> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(UserBill::getUserId, userId)
                .eq(UserBill::getCategory, UserBillCategoryEnum.PROFIT.getCategory())
                .ne(UserBill::getNumber,0)
                .orderByDesc(UserBill::getCreateTime);
        List<UserBill> records = this.page(new Page<>(page, size), wrapper).getRecords();
        return UserBillConverter.toVoList(records);
    }

    @Override
    @Transactional(rollbackFor = ServiceException.class)
    public void appWithdraw(Long userId, ApplyWithdrawDTO dto) {

//        if (dto.getNumber().doubleValue()>2000){
//            throw new ServiceException("单笔提现不能超过2000元！");
//        }

//        Boolean obj = redisCache.getCacheObject("withdraw_" + userId);

//        if (obj==null){
//            redisCache.setCacheObject("withdraw_"+userId,Boolean.TRUE,1, TimeUnit.DAYS);
//        }else {
//            throw new ServiceException("一天只允许提现一次哦！");
//        }

        User user = userService.getById(userId);
        if (user.getTotalProfit().doubleValue()<dto.getNumber().doubleValue()){
            throw new ServiceException("申请提现失败，收益不足提现额度。");
        }
        userService.subProfit(userId, dto.getNumber());
        Long withdrawId = userWithdrawService.applyWithdraw(userId, dto);
        UserBill userBill = new UserBill();
        userBill.setUserId(userId);
        userBill.setTargetId(withdrawId);
        userBill.setCategory(UserBillCategoryEnum.PROFIT.getCategory());
        userBill.setPm(0);
        userBill.setDescription("收益提现");
        userBill.setStatus(Status.PENDING.getValue());
        userBill.setType(UserBillTypeEnum.WITHDRAW.getType());
        userBill.setNumber(dto.getNumber());
        this.save(userBill);


    }

    @Override
    public List<UserBillVO> getWithdrawRecords(Long userId, Integer page, Integer size) {
        LambdaQueryWrapper<UserBill> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(UserBill::getUserId, userId)
                .eq(UserBill::getCategory, UserBillCategoryEnum.PROFIT.getCategory())
                .eq(UserBill::getType, UserBillTypeEnum.WITHDRAW.getType())
                .orderByDesc(UserBill::getCreateTime);
        List<UserBill> records = this.page(new Page<>(page, size), wrapper).getRecords();
        return UserBillConverter.toVoList(records);
    }

    @Override
    public List<PartyUserBillVO> getContributionList(Long partyId, Integer type) {
        //获取派对贡献榜单
        return baseMapper.getContributionList(partyId,type);
    }


    /**
     * 获取总流水金额
     * @return
     */
    @Override
    public Double getTotalBillNumber(String partyId,Integer type){
        Double totalBillNumber = baseMapper.getTotalBillNumber(partyId, type);
        if (totalBillNumber == null || totalBillNumber<=0){
            return 0d;
        }
        return BigDecimal.valueOf(totalBillNumber).setScale(2, RoundingMode.HALF_UP).doubleValue();
    }

    @Override
    public List<PartyUserBillVO> getCharmList(Long partyId, Integer type) {
        //获取派对贡献榜单
        return baseMapper.getCharmList(partyId, type);
    }

    @Override
    public Double getMonthProfit(Long userId) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime firstDay = now.with(TemporalAdjusters.firstDayOfMonth()); // 获取当前月的第一天
        LocalDateTime lastDay = now.with(TemporalAdjusters.lastDayOfMonth()); // 获取当前月的最后一天
        LambdaQueryWrapper<UserBill> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(UserBill::getUserId,userId)
                .eq(UserBill::getCategory, UserBillCategoryEnum.PROFIT.getCategory())
                .eq(UserBill::getStatus, Status.SUCCESS.getValue())
                .ge(UserBill::getCreateTime, firstDay)
                .le(UserBill::getCreateTime, lastDay);
        List<UserBill> list = this.list(wrapper);
        BigDecimal totalNumber = BigDecimal.ZERO;
        for (UserBill userBill : list) {
            BigDecimal number = userBill.getNumber();
            totalNumber = totalNumber.add(number);
        }
        return totalNumber.setScale(2, RoundingMode.HALF_UP).doubleValue();
    }

    @Override
    public void systemEditBalance(Long userId, BigDecimal number, Integer type) {
        UserBill userBill = new UserBill();
        userBill.setUserId(userId);
        userBill.setTargetId(userId);
        userBill.setCategory(UserBillCategoryEnum.BALANCE.getCategory());
        if (type == 1){
            userBill.setPm(1);
            userBill.setDescription("系统增加余额");
        }else if (type == -1){
            userBill.setPm(-1);
            userBill.setDescription("系统减少余额");
        }
        userBill.setStatus(Status.PENDING.getValue());
        userBill.setType(UserBillTypeEnum.SYSTEM.getType());
        userBill.setNumber(number);
        this.save(userBill);
    }

    @Override
    public void systemEditProfit(Long userId, BigDecimal number, Integer type) {
        UserBill userBill = new UserBill();
        userBill.setUserId(userId);
        userBill.setTargetId(userId);
        userBill.setCategory(UserBillCategoryEnum.BALANCE.getCategory());
        if (type == 1){
            userBill.setPm(1);
            userBill.setDescription("系统增加收益");
        }else if (type == -1){
            userBill.setPm(-1);
            userBill.setDescription("系统减少收益");
        }
        userBill.setStatus(Status.PENDING.getValue());
        userBill.setType(UserBillTypeEnum.SYSTEM.getType());
        userBill.setNumber(number);
        this.save(userBill);
    }

    /**
     * 获取房间流水
     * @param id
     * @param type 1总流水，0 周流水，-1月流水
     * @return
     */
    @Override
    public Double getPartyBill(String id, Integer type) {
//        Double number = baseMapper.getPartyBill(id, type);
        return null;
    }

    @Override
    public Double getPartyBill(List<String> partyIds) {
        LambdaQueryWrapper<UserBill> wrapper = Wrappers.lambdaQuery();
        wrapper.in(UserBill::getPartyId, partyIds)
                .eq(UserBill::getType,UserBillTypeEnum.PARTY_GIFT.getType())
                .eq(UserBill::getCategory, UserBillCategoryEnum.BALANCE.getCategory());


        return this.list(wrapper).stream().map(UserBill::getNumber).mapToDouble(BigDecimal::doubleValue).sum();
    }

    @Override
    public List<PartyUserBillVO> getContributionTopThree(Long partyId) {
        //获取派对贡献榜单
        return baseMapper.getContributionTopThree(partyId);
    }

    @Override
    public IPage<UserBillVO> getSystemUpdateBalanceList(Integer page, Integer size) {

        return baseMapper.getSystemUpdateBalanceList(new Page<>(page,size));

    }
}
